package com.srwl.mytx.activity;

import android.Manifest;
import android.animation.ObjectAnimator;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Rect;
import android.graphics.RectF;
import android.hardware.Camera;
import android.media.MediaMetadataRetriever;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.util.Size;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;

import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import com.cjt2325.cameralibrary.util.ScreenUtils;
import com.srwl.mytx.R;
import com.srwl.mytx.camera2.AutoFitTextureView;
import com.srwl.mytx.camera2.CameraController;
import com.srwl.mytx.camera2.ICamera;
import com.srwl.mytx.tao.av.CameraHelper;
import com.srwl.mytx.tao.av.ClipManager;
import com.srwl.mytx.tao.av.FileUtils;
import com.srwl.mytx.tao.av.SystemUtil;
import com.srwl.mytx.tao.av.VideoBean;
import com.srwl.mytx.utils.VideoUtil;
import com.srwl.mytx.widget.ConfirmDialog;
import com.srwl.mytx.widget.RecordTimelineView;

import java.io.File;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Formatter;
import java.util.List;
import java.util.Locale;
import java.util.UUID;


public class VideoRecordActivityV2 extends BaseActivity implements View.OnClickListener {
    private static final String TAG = VideoRecordActivityV2.class.getSimpleName();
    private final int PERMISSION_REQUEST_CODE = 100; //权限申请请求码
    private static int REQUEST_CODE_VIDEO_PLAYER = 101;
    private boolean granted = false;
    private String path;
    private ImageView iv_back; //退出
    private ImageView iv_light; //闪光灯
    private ImageView iv_cameraChoose;// 摄像头选择

    private AutoFitTextureView surfaceView; //显示摄像头预览画面
    private ImageView iv_recorder;  //录制按键
    private ImageView iv_recorPause; //录制暂停：实际上是停止录制，最后的完成录制的时候，是把几个录制的视频片段拼接成一个视频
    private CheckBox cb_deleteVideoClip;//删除最后一个视频片段
    private ImageView iv_commit; //完成视频录制确定按键
    private TextView tv_recordTime;
    private TextView tv_videoTooShort;
    private RecordTimelineView recordTimelineView;
    private ProgressBar progressBar;
    //  private MediaRecorder mediaRecorder;
    private Camera camera;
    private Camera.Parameters parameters;

    private boolean isRecording;//标记是否增长录制
    private Handler mSafeHandler;
    private ClipManager mClipManager; //视频片段管理者，有删除片段等功能
    private int maxDuration = 20000;//视频录制最长时间 20s 视频差不多是2M多
    private int minDuration = 3000;
    private int currentDuration = 0;
    private StringBuilder mFormatBuilder;
    private Formatter mFormatter;
    private Runnable _runnableTimer;
    private long startTime;
    private int mVideoIndex = -1;//视频片段索引
    private String dir;//视频存储路径
    private Animation scaleAnimation;
    private Animation alpahAnimation;
    private Camera.Size optimalSize;//最优预览尺寸
    private long lastRecordClickTime;
    private int cameraPosition;
    private List<String> clipPaths = new ArrayList<>();

    private int handlerTime;

    private CameraController cameraController;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_video_recorder_v2);
        dir = this.getExternalCacheDir().getAbsolutePath() + File.separator + "short_video";
        File file = new File(dir);
        if (!file.exists()) {
            file.mkdirs();
        }
        cameraController = new CameraController(this);
        cameraController.setFolderPath(dir);
        initView();
        initClipManager();
        alpahAnimation = AnimationUtils.loadAnimation(this, R.anim.taorecorder_alpha_reverse);
        scaleAnimation = AnimationUtils.loadAnimation(this, R.anim.taorecorder_scale_reverse);

        cameraPosition = SystemUtil.getCameraFacingBack();//第一次开启后面的摄像头

        // mediaRecorder = new MediaRecorder();

        mFormatBuilder = new StringBuilder();
        mFormatter = new Formatter(mFormatBuilder, Locale.getDefault());
        initTimer();
        CameraTouch cameraTouch=new CameraTouch();
        surfaceView.setOnTouchListener(new View.OnTouchListener() {

            private long mClickOn;
            private float mLastX;
            private float mLastY;

            @Override
            public boolean onTouch(View v, MotionEvent event) {
//                if (TEXTURE_STATE == TEXTURE_PLAY_STATE)
//                    return true;
                switch (event.getActionMasked()) {
                    case MotionEvent.ACTION_DOWN:
                        if (event.getPointerCount() == 1) {
                            mClickOn = System.currentTimeMillis();
                            mLastX = event.getX();
                            mLastY = event.getY();
                        }
                        break;
                    case MotionEvent.ACTION_UP:
                        if (event.getPointerCount() == 1) {
                            if ((System.currentTimeMillis() - mClickOn) < 500) {
                                //requestFocus((int) event.getX(), (int) event.getY());
                            }
                        }
                        break;
                    case MotionEvent.ACTION_POINTER_DOWN:
                        cameraTouch.onScaleStart(event);
                        break;
                    case MotionEvent.ACTION_MOVE:
                        if (event.getPointerCount() == 2) {
                            cameraTouch.onScale(event);
                        } else {
                            float x = event.getX() - mLastX;
                            float y = event.getY() - mLastY;
                            if (Math.abs(x) >= 10 || Math.abs(y) >= 10) {
                                mClickOn = 0;
                            }
                        }
                        break;
                    case MotionEvent.ACTION_POINTER_UP:
                        cameraTouch.onScaleEnd(event);
                        break;
                }
//                CameraCharacteristics characteristics = null;
//                try {
//                    characteristics = manager.getCameraCharacteristics(mCameraId);
//                } catch (CameraAccessException e) {
//                    e.printStackTrace();
//                }
//                float maxzoom = (characteristics.get(CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM)) * 10;
//
//
//                Rect m = characteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
//                int action = event.getAction();
//                float current_finger_spacing;
//
//                if (event.getPointerCount() > 1) {
//                    // Multi touch logic
//                    current_finger_spacing = getFingerSpacing(event);
//                    if (finger_spacing != 0) {
//                        if (current_finger_spacing > finger_spacing && maxzoom > zoom_level) {
//                            zoom_level++;
//                        } else if (current_finger_spacing < finger_spacing && zoom_level > 1) {
//                            zoom_level--;
//                        } else {
//                            Log.i(TAG, "onTouch: 缩放登记没有变" + zoom_level);
//                            return true;
//                        }
//                        int minW = (int) (m.width() / maxzoom);
//                        int minH = (int) (m.height() / maxzoom);
//                        int difW = m.width() - minW;
//                        int difH = m.height() - minH;
//                        int cropW = difW / 100 * (int) zoom_level;
//                        int cropH = difH / 100 * (int) zoom_level;
//                        cropW -= cropW & 3;
//                        cropH -= cropH & 3;
//                        Rect zoom = new Rect(cropW, cropH, m.width() - cropW, m.height() - cropH);
//                        mPreviewBuilder.set(CaptureRequest.SCALER_CROP_REGION, zoom);
//                        updatePreview();
//                    }
//                    finger_spacing = current_finger_spacing;
//                } else {
//                    if (action == MotionEvent.ACTION_UP) {
//                        //single touch logic
//                    }
//                }


                return true;
            }
        });
    }


    private void initTimer() {
        //本来我想在用Timer  TimerTask,但是考虑到TimerTask是非Ui线程，每次更新ui还得用handler,或者runOnUiThread,可能性能还不如这个Runnable，但是用Timer 逻辑更清晰，
        _runnableTimer = new Runnable() {
            public void run() {

                if (startTime == 0L && !isRecording) {
                    getSafeHandler().postDelayed(this, 25L);
                } else {
                    if (startTime == 0L) {
                        startTime = System.currentTimeMillis();
                    }
                    long currentClipDuration = (System.currentTimeMillis() - startTime);
                    recordTimelineView.setDuration((int) currentClipDuration);//设置当前视频片段的长度
                    mClipManager.onRecordFrame(currentClipDuration);
                    setRecordTime();
                    if (mClipManager.isMinDurationReached()) {
                        iv_commit.setVisibility(View.VISIBLE);
                    }

                    if (mClipManager.isMaxDurationReached()) {
                        stopRecord();
                    } else {
                        getSafeHandler().postDelayed(this, 25L);
                    }
                }

            }
        };
    }

    /**
     * 初始化视频片段管理器
     */
    private void initClipManager() {
        mClipManager = new ClipManager();
        mClipManager.setMaxDuration(maxDuration);
        mClipManager.setMinDuration(minDuration);
    }

    private void initView() {
        iv_back = findViewById(R.id.iv_back);
        iv_light = findViewById(R.id.iv_light);
        iv_cameraChoose = findViewById(R.id.iv_camera_choose);
        surfaceView = findViewById(R.id.camera_view);
        iv_recorder = findViewById(R.id.iv_recorder);
        cb_deleteVideoClip = findViewById(R.id.btn_delete_last_clip);
        iv_recorPause = findViewById(R.id.iv_record_pause);
        iv_commit = findViewById(R.id.iv_commit);
        tv_videoTooShort = findViewById(R.id.tv_video_too_short);
        tv_videoTooShort.setAlpha(0f);
        tv_recordTime = findViewById(R.id.tv_record_time);
        progressBar = findViewById(R.id.progress_bar);
        recordTimelineView = findViewById(R.id.record_time_line);
        recordTimelineView.setMaxDuration(maxDuration);
        recordTimelineView.setMinDuration(minDuration);
        recordTimelineView.setColor(R.color.holo_red_light, R.color.yancy_indigo600, R.color.common_white, R.color.half_transparent_white);
        iv_back.setOnClickListener(this);
        iv_light.setOnClickListener(this);
        iv_cameraChoose.setOnClickListener(this);
        iv_recorder.setOnClickListener(this);
        cb_deleteVideoClip.setOnClickListener(this);
        iv_commit.setOnClickListener(this);
//        surfaceView.setOnTouchListener(new View.OnTouchListener() {
//            @Override
//            public boolean onTouch(View v, MotionEvent event) {
//
//                switch (event.getAction()) {
//                    case MotionEvent.ACTION_DOWN:
//                        if (event.getPointerCount() == 1) {//一个手指点击
//                            handleFocus(event.getX(), event.getY());
//                        }
//                        break;
//                }
//
//                return false;
//            }
//        });
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.iv_back:
                onBackPress();

                break;
            case R.id.iv_light:
                changeLight();

                break;
            case R.id.iv_camera_choose:
                rotateCamera();
                break;

            case R.id.iv_recorder:

                Long currentTime = System.currentTimeMillis();
                if (currentTime - lastRecordClickTime < 500) {//防止误击
                    return;
                }
                lastRecordClickTime = currentTime;
                if (isRecording) {
                    stopRecord();

                } else {
                    startRecord();

                }

                break;
            case R.id.btn_delete_last_clip:

                if (cb_deleteVideoClip.isChecked()) {//点一次，：显示最后一段视频被选中
                    recordTimelineView.selectLast();
                    cb_deleteVideoClip.setChecked(true);
                } else { //再点一次：删除
                    mClipManager.removeLastClip();
                    recordTimelineView.deleteLast();
                    cb_deleteVideoClip.setChecked(false);
                    cb_deleteVideoClip.setEnabled(mClipManager.isUnEmpty());
                    int totalRecordTime = mClipManager.getDuration();
                    if (totalRecordTime < minDuration) {
                        iv_commit.setVisibility(View.GONE);
                    }
                    setRecordTime();
                    clipPaths.remove(mVideoIndex);
                    mVideoIndex--;
                    if (mVideoIndex == -1) {//如果视频片段全部删完了，则显示摄像头切换图标
                        iv_cameraChoose.setVisibility(View.VISIBLE);
                    }
                }
                break;
            case R.id.iv_commit:
                toIMPlayRecordVideoActivity();

        }
    }

    private void showProgressBar() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                progressBar.setVisibility(View.VISIBLE);
            }
        });
    }

    private void hideProgressBar() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                progressBar.setVisibility(View.GONE);
            }
        });
    }

    /**
     * 显示界面上的录像时间
     */
    private void setRecordTime() {
        int totaltime = mClipManager.getDuration();

        if (totaltime >= 0 && totaltime < maxDuration) {
            mFormatBuilder.setLength(0);
            String stime = mFormatter.format("%d.%d 秒", totaltime / 1000, totaltime / 100 % 10).toString();
            tv_recordTime.setText(stime);
        }

    }

    //闪光灯设置切换
    private void changeLight() {
        Object o = iv_light.getTag();
        if (o == null || ((int) o) == 0) {
            iv_light.setImageResource(R.drawable.aliwx_sv_wx_shiny_pre);
            iv_light.setTag(1);
            cameraController.flashSwitchState(CameraController.FlashState.OPEN);
        } else {
            iv_light.setImageResource(R.drawable.aliwx_sv_wx_shiny_nor);
            iv_light.setTag(0);
            cameraController.flashSwitchState(CameraController.FlashState.CLOSE);
        }
    }

    private void rotateCamera() {

        CameraController.CameraType cameraType = cameraController.switchCamera();
        if (cameraType == CameraController.CameraType.FRONT) {
            iv_light.setVisibility(View.INVISIBLE);
        } else {
            iv_light.setVisibility(View.VISIBLE);
        }
    }


    public void startRecord() {

        iv_recorder.startAnimation(alpahAnimation);//显示呼吸效果动画
        iv_recorPause.setVisibility(View.VISIBLE);//显示暂停图标
        iv_commit.setEnabled(false);//录制过程中禁用 提交按键
        iv_cameraChoose.setVisibility(View.INVISIBLE);//一旦开始录制，就一直隐藏切换摄像头图标，因为前后摄像头录制的视频方向不一致，合并处理的视频，方向有问题
        cb_deleteVideoClip.setVisibility(View.VISIBLE);
        cb_deleteVideoClip.setEnabled(false);
        cb_deleteVideoClip.setChecked(false);
        //每次开始录像，生成一个VideoBean，添加进ClipManager
        VideoBean vb = new VideoBean();
        mVideoIndex++;//每录制一段视频，索引增加一次，
        String clipPath = dir + File.separator + getLastOutputFileName();
        vb.videoFile = clipPath;
        mClipManager.onRecordStarted(vb);
        clipPaths.add(clipPath);
        //重置录像的开始时间点
        startTime = 0L;
        //开始记录录像时间
        getSafeHandler().post(_runnableTimer);
        cameraController.setFilePath(clipPath);
        cameraController.startRecordingVideo();
        Log.i(TAG, "startRecord: 开始录制。。。。");
        isRecording = true;
    }

    private String getLastOutputFileName() {
        return "temp_" + mVideoIndex + ".mp4";
    }


    public void stopRecord() {
//        if (maxDuration - mClipManager.getDuration() < 1000 && maxDuration - mClipManager.getDuration() > 100) {//如果停止的时间点与最大录制时间只差1s，那就让它录制到最大录制时
//            Log.e(TAG, "stopRecord: 距离视频录制最大时间不到1s，让他自动停止，");
//            return;
//        } else if (maxDuration - mClipManager.getDuration() < 100) {//禁用录制按键
//            iv_recorder.setEnabled(false);
//            iv_recorder.setAlpha(0.5f);
//        }
        Log.i(TAG, "startRecord: 停止录制。。。。");
        cameraController.stopRecordingVideo();
        iv_commit.setEnabled(true);
        // iv_cameraChoose.setVisibility(View.VISIBLE); //一旦录制一次后，就禁用切换摄像头，因为前后摄像头录制的视频合并处理，方向有问题，
        iv_recorder.clearAnimation();//清除动画
        iv_recorPause.setVisibility(View.INVISIBLE);//隐藏暂停图标
        mClipManager.onRecordPaused();
        if (mSafeHandler != null) {
            getSafeHandler().removeCallbacks(_runnableTimer);
        }
        if (System.currentTimeMillis() - startTime < 1000) {//录制时间小于1S 丢弃,因为MediaRecorder 录制时间太短就停止录制会奔溃，找不到原因，所以当录制时间小于1s的时间，直接重置MediaRecorder
            mClipManager.removeLastClip();//把最后一条视频片段删除
            recordTimelineView.setDuration(0);//设置当前视频片段的长度为0
            setRecordTime();//重新设置拍摄进度
            // mediaRecorder.reset();//重置MediaRecorder
            clipPaths.remove(mVideoIndex);//清除当前视频片段的地址记录
            mVideoIndex--;
            ObjectAnimator animator_txt_tip = ObjectAnimator.ofFloat(tv_videoTooShort, "alpha", 1f, 0f);
            animator_txt_tip.setDuration(2000);
            animator_txt_tip.start();

        } else {
            recordTimelineView.clipComplete();
//            mediaRecorder.setPreviewDisplay(null);
//            mediaRecorder.stop();
//            mediaRecorder.reset();
            // String targetPath = mClipManager.getClip(mVideoIndex).videoFile;
            // final String outPutPath = targetPath.replace(".mp4", System.currentTimeMillis() + ".mp4");
            //   String[] command = new String[]{"-i" , targetPath,"-metadata:s:v","rotate=\"180\"", outPutPath }; //这个命令只是修改rotate 的值，就是修改OrientationHint的值，


        }
        cb_deleteVideoClip.setEnabled(mClipManager.isUnEmpty());

        isRecording = false;
    }

    private Handler getSafeHandler() {
        if (mSafeHandler != null) {
            return mSafeHandler;
        } else {
            mSafeHandler = new Handler();
            return mSafeHandler;
        }
    }

    @Override
    protected void onStart() {
        super.onStart();
        //全屏显示
        if (Build.VERSION.SDK_INT >= 19) {
            View decorView = getWindow().getDecorView();
            decorView.setSystemUiVisibility(
                    View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                            | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                            | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                            | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                            | View.SYSTEM_UI_FLAG_FULLSCREEN
                            | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
        } else {
            View decorView = getWindow().getDecorView();
            int option = View.SYSTEM_UI_FLAG_FULLSCREEN;
            decorView.setSystemUiVisibility(option);
        }


        // getPermissions();
    }

    /**
     * 获取权限
     */
    private void getPermissions() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED &&
                    ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED &&
                    ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
                //具有权限
                granted = true;
            } else {
                //不具有获取权限，需要进行权限申请
                ActivityCompat.requestPermissions(this, new String[]{
                        Manifest.permission.WRITE_EXTERNAL_STORAGE,
                        Manifest.permission.RECORD_AUDIO,
                        Manifest.permission.CAMERA}, PERMISSION_REQUEST_CODE);
                granted = false;
            }
        }
    }

    @TargetApi(23)
    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == PERMISSION_REQUEST_CODE) {
            int size = 0;
            if (grantResults.length >= 1) {
                int writeResult = grantResults[0];
                //读写内存权限
                boolean writeGranted = writeResult == PackageManager.PERMISSION_GRANTED;//读写内存权限
                if (!writeGranted) {
                    size++;
                }
                //录音权限
                int recordPermissionResult = grantResults[1];
                boolean recordPermissionGranted = recordPermissionResult == PackageManager.PERMISSION_GRANTED;
                if (!recordPermissionGranted) {
                    size++;
                }
                //相机权限
                int cameraPermissionResult = grantResults[2];
                boolean cameraPermissionGranted = cameraPermissionResult == PackageManager.PERMISSION_GRANTED;
                if (!cameraPermissionGranted) {
                    size++;
                }
                if (size == 0) {
                    granted = true;

                } else {
                    showToast("请到设置-权限管理中开启");
                    finish();
                }
            }
        }
    }


    private int generateVideoFrameRate(List<int[]> supportedPreviewFpsRange) {
        int frameRate = 30;
//        for (int[] ints : supportedPreviewFpsRange) {
//            Log.d(TAG, "generateVideoFrameRate: min: " + ints[0] + " max: " + ints[1]);
//            if (ints[0] == 30000 || ints[1] == 30000) {
//                frameRate = 30;
//                break;
//            } else if (ints[0] == 24000 || ints[1] == 24000) {
//                frameRate = 24;
//                break;
//            } else if (ints[0] == 20000 || ints[1] == 20000) {
//                frameRate = 20;
//                break;
//            } else if (ints[0] == 15000 || ints[1] == 15000) {
//                frameRate = 15;
//                break;
//            } else if (ints[0] == 7000) {
//                frameRate = 7;
//                break;
//            }
//
//        }

        for (int i = supportedPreviewFpsRange.size() - 1; i >= 0; i--) {
            int[] ints = supportedPreviewFpsRange.get(i);
            Log.d(TAG, "generateVideoFrameRate: min: " + ints[0] + " max: " + ints[1]);
            if (ints[0] == 30000 || ints[1] == 30000) {
                frameRate = 30;
                break;
            } else if (ints[0] == 24000 || ints[1] == 24000) {
                frameRate = 24;
                break;
            } else if (ints[0] == 20000 || ints[1] == 20000) {
                frameRate = 20;
                break;
            } else if (ints[0] == 15000 || ints[1] == 15000) {
                frameRate = 15;
                break;
            } else if (ints[0] == 7000) {
                frameRate = 7;
                break;
            }
        }
        return frameRate;
    }

    private Camera.Size getSupportedVideoSizes(List<Camera.Size> supportedVideoSizes) {

        for (Camera.Size supportedVideoSize : supportedVideoSizes) {
            Log.d(TAG, "getSupportedVideoSizes: with:" + supportedVideoSize.width + "   height:" + supportedVideoSize.height);
            if (supportedVideoSize.width == 1280 && supportedVideoSize.height == 720) {
                return supportedVideoSize;
            } else if (supportedVideoSize.width == 864) {
                return supportedVideoSize;
            } else if (supportedVideoSize.width == 800) {
                return supportedVideoSize;
            } else if (supportedVideoSize.width == 720) {
                return supportedVideoSize;
            } else if (supportedVideoSize.width == 640) {
                return supportedVideoSize;
            } else if (supportedVideoSize.width == 480) {
                return supportedVideoSize;
            } else if (supportedVideoSize.width == 352) {
                return supportedVideoSize;
            }
        }

        return supportedVideoSizes.get(0);
    }

    /**
     * 同时从 分辨率高宽比和像素点面积两个维度来判断各个预览分辨率与目标分辨率的差别
     * 差别最小的，作为预览分辨率
     * 经过但愿测试 非常科学
     *
     * @param previewSizes
     * @param surfaceViewWidth
     * @param surfaceViewHeight
     * @return
     */
    private Camera.Size getOptimalVideoSize_new(List<Camera.Size> previewSizes, int surfaceViewWidth, int surfaceViewHeight) {
        Camera.Size previewSize = null;
        double totalDifference = Double.MAX_VALUE;
        double targetRatio = (double) surfaceViewHeight / surfaceViewWidth;
        Log.i(TAG, "getOptimalVideoSize_new: targetRatio :" + targetRatio);
        long targetArea = surfaceViewWidth * surfaceViewHeight;
        Log.i(TAG, "getOptimalVideoSize_new: targetArea :" + targetArea);
        for (int i = 0; i < previewSizes.size(); i++) {
            double ratio = ((double) previewSizes.get(i).width) / previewSizes.get(i).height;
            double ratioDifference = Math.abs(ratio - targetRatio);
            Camera.Size size = previewSizes.get(i);
            long area = size.width * previewSizes.get(i).height;
            double areaDifference = (double) Math.abs(area - targetArea) / targetArea;
            double currentTotalDifference = ratioDifference + areaDifference;
            //计算方差,估计叫 方差 ，表示数据的离散程度，我们希望找到 在面积、高宽比都与期望值比较接近的，而不是一个完全一样，一个相去甚远，好比是寻找学生中 成绩总体不错的，而不是要 偏科生。
            double variance = (Math.pow((Math.abs(ratioDifference - currentTotalDifference / 2)), 2) + Math.pow((Math.abs(areaDifference - currentTotalDifference / 2)), 2)) / 2;
            Log.i(TAG, "getOptimalVideoSize_new: variance :" + variance);
            currentTotalDifference = currentTotalDifference + variance;
            Log.i(TAG, "getOptimalVideoSize_new: currentTotalDifference :" + currentTotalDifference + " size.width:" + size.width + "  size.height:" + size.height);
            if (currentTotalDifference < totalDifference) {
                totalDifference = currentTotalDifference;
                previewSize = size;
            }
        }
        return previewSize;
    }


    private Camera.Size getOptimalVideoSize(List<Camera.Size> supportedVideoSizes,
                                            List<Camera.Size> previewSizes, int w, int h) {
// Use a very small tolerance because we want an exact match.
        final double ASPECT_TOLERANCE = 0.1;
        double targetRatio = (double) w / h;

// Supported video sizes list might be null, it means that we are allowed to use the preview
// sizes
        List<Camera.Size> videoSizes;
        if (supportedVideoSizes != null) {
            videoSizes = supportedVideoSizes;
        } else {
            videoSizes = previewSizes;
        }
        Camera.Size optimalSize = null;

// Start with max value and refine as we iterate over available video sizes. This is the
// minimum difference between view and camera height.
        double minDiff = Double.MAX_VALUE;

// Target view height
        int targetHeight = h;

// Try to find a video size that matches aspect ratio and the target view size.
// Iterate over all available sizes and pick the largest size that can fit in the view and
// still maintain the aspect ratio.
        for (Camera.Size size : videoSizes) {
            double ratio = (double) size.width / size.height;
            if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)
                continue;
            if (Math.abs(size.height - targetHeight) < minDiff && previewSizes.contains(size)) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }

// Cannot find video size that matches the aspect ratio, ignore the requirement
        if (optimalSize == null) {
            minDiff = Double.MAX_VALUE;
            for (Camera.Size size : videoSizes) {
                if (Math.abs(size.height - targetHeight) < minDiff && previewSizes.contains(size)) {
                    optimalSize = size;
                    minDiff = Math.abs(size.height - targetHeight);
                }
            }
        }
        return optimalSize;
    }

    /**
     * 合并视频
     */
    private void toIMPlayRecordVideoActivity() {


        (new Thread(new Runnable() {
            public void run() {


                showProgressBar();
                final String tempVideoPath = dir + File.separator + "temp_output.mp4";
                final String rotateVideoPath = dir + File.separator + "temp_rotate_output.mp4";

                FileUtils.deleteFile(tempVideoPath);
                //合并视频片段
                // MediaEncoderMgr.mergeMp4Files(input, tempVideoPath); // 阿里VideoSDK 有问题，全部是后摄像头拍摄的视频情况下，方向也不对，
                VideoUtil.appendMp4List(clipPaths, tempVideoPath);//mp4parser 当视频的方向信息不一致时候，有问题，就是前后摄像头都录制了视频片段的时候，播放的时候，有的就是倒立的了，
                toPlayerActivity(tempVideoPath);

            }
        })).start();
    }

    private void toPlayerActivity(String tempVideoPath) {
        String UUIDString = UUID.randomUUID().toString().replaceAll("-", "");
        // final String targetVideoPath = dir + File.separator + UUIDString + "_output.mp4";
        // FileUtils.copyFile(tempVideoPath, targetVideoPath);
        hideProgressBar();
        getSafeHandler().post(new Runnable() {
            public void run() {

                // Bundle bundle = getIntent().getExtras();
                Bundle bundle = new Bundle();
                BigDecimal duration = new BigDecimal(mClipManager.getDuration());
                BigDecimal ms = new BigDecimal(1000);
                int returnValue = duration.divide(ms, 0, 1).intValue();
                bundle.putInt("videoDuration", returnValue);


                BitmapFactory.Options decodeOptions = new BitmapFactory.Options();
                decodeOptions.inJustDecodeBounds = true;


                int size = 0;
                if ((new File(tempVideoPath)).isFile()) {
                    File file = new File(tempVideoPath);
                    size = (int) file.length();
                    Log.i(TAG, "run: 视频大小： " + size);
                    Log.i(TAG, "run: 视频地址：" + tempVideoPath);
                }

                bundle.putCharSequence("videoPath", tempVideoPath);

                Intent intent = new Intent(VideoRecordActivityV2.this, VideoCoverSelectActivity.class);
                intent.putExtras(bundle);
                // intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);//跳转到MyVideoPlayActivity后，不能finish本activity,因为用户可能返回来继续编辑
                startActivityForResult(intent, REQUEST_CODE_VIDEO_PLAYER);
                overridePendingTransition(R.anim.taorecorder_push_left_in, R.anim.taorecorder_push_left_out);
                //   finish();

            }
        });
    }

    private Bitmap getVideoThumb(String path) {
        MediaMetadataRetriever media = new MediaMetadataRetriever();
        media.setDataSource(path);
        return media.getFrameAtTime();
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();

        if (alpahAnimation != null) {
            alpahAnimation.cancel();
            alpahAnimation.reset();
            alpahAnimation = null;
        }
    }

    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            onBackPress();
            return true;

        } else {
            return super.onKeyDown(keyCode, event);
        }
    }

    private void onBackPress() {
        if (isRecording) {
            return;
        }
        if (mClipManager.isUnEmpty()) {
            ConfirmDialog dialog = new ConfirmDialog(this, "提醒", "确定放弃已经录制的视频?", true);
            dialog.show();
            dialog.setConfirmListener(new ConfirmDialog.ConfirmListener() {
                @Override
                public void confirm() {
                    FileUtils.clearTempFiles(dir);
                    finish();
                }
            });
        } else {
            finish();
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (REQUEST_CODE_VIDEO_PLAYER == requestCode) {
            if (RESULT_OK == resultCode) {
                setResult(RESULT_OK, data);
                finish();
            }
        }
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return super.onTouchEvent(event);

    }


    @Override
    protected void onResume() {
        super.onResume();
        cameraController.startBackgroundThread();
        cameraController.initCamera(surfaceView);
    }


    @Override
    protected void onPause() {
        super.onPause();
        if (isRecording) {
            stopRecord();
        }

        // closeCamera();
        cameraController.stopBackgroundThread();

    }


    private class CameraTouch {
        private float mOldScale = 1.0f;
        private float mScale;
        private float mSpan = 0;
        private float mOldSpan;
        private float mFirstDistance = 0;

        public void onScale(MotionEvent event) {
            if (event.getPointerCount() == 2) {
                if (mFirstDistance == 0)
                    mFirstDistance = distance(event);

                float distance = distance(event);
                float scale;
                if (distance > mFirstDistance) {
                    scale = (distance - mFirstDistance) / 80;
                    scale = scale + mSpan;
                    mOldSpan = scale;
                    mScale = scale;
                } else if (distance < mFirstDistance) {
                    scale = distance / mFirstDistance;
                    mOldSpan = scale;
                    mScale = scale * mOldScale;
                } else {
                    return;
                }

                cameraController.cameraZoom(mScale);
                //  mScaleSeekBar.setProgress((int) ((mScale / cameraHelper.getMaxZoom()) * mScaleSeekBar.getMax()));
                //if (mScale < 1.0f)
                //mScaleSeekBar.setProgress(0);
            }
        }

        public void onScaleStart(MotionEvent event) {
            mFirstDistance = 0;
            //setScaleMax((int) cameraHelper.getMaxZoom());

            //  mSeekBarLayout.setVisibility(View.VISIBLE);
            //   removeSeekBarRunnable();
            Log.e("scale", "scale:start");
        }

        public void onScaleEnd(MotionEvent event) {
            if (mScale < 1.0f)
                mOldScale = 1.0f;
            else if (mScale > cameraController.getMaxZoom())
                mOldScale = cameraController.getMaxZoom();
            else
                mOldScale = mScale;
            mSpan = mOldSpan;

            if (event != null)
                //  seekBarDelayedHind();
                Log.e("scale", "scale:end");
        }

        public void resetScale() {
            mOldScale = 1.0f;
            mSpan = 0f;
            mFirstDistance = 0f;
            // mScaleSeekBar.setProgress(0);
        }

        public void setScale(float scale) {
            mScale = scale;
            mOldSpan = scale;
            onScaleEnd(null);
        }

        /**
         * 计算两个手指间的距离
         *
         * @param event
         * @return
         */
        private float distance(MotionEvent event) {
            float dx = event.getX(1) - event.getX(0);
            float dy = event.getY(1) - event.getY(0);
            /** 使用勾股定理返回两点之间的距离 */
            return (float) Math.sqrt(dx * dx + dy * dy);
        }

        private void setScaleMax(int max) {
            // mScaleSeekBar.setMax(max * 100);
        }
    }


}
